#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/signalfd.h>
#include <sys/types.h>
#include "signal_watcher.h"

int32_t ON_MSG = SIGRTMIN + 7;

class signal_mgr {
public:
    MAKE_NONCOPYABLE(signal_mgr);
    signal_mgr(uv_loop_t* loop): sw_(nullptr), loop_(loop) {}
    int watch_signals();
    void handle_signal(const signalfd_siginfo*);

private:
    int send_signal(int dest_pid, int signo);

private:
    signal_watcher* sw_;
    uv_loop_t* loop_;
};

int signal_mgr::send_signal(int dest_pid, int signo) {
    static pid_t pid = getpid();
    
    sigval value;
    memset(&value, 0x00, sizeof(sigval));
    value.sival_int = pid;

    int ret = sigqueue(dest_pid, signo, value);
    if (ret != 0)
        perror("sigqueue error");

    return ret;
}

int signal_mgr::watch_signals() {
    sw_ = signal_watcher::create(loop_);

    if (!sw_) {
        sk_error("create signal watcher error");
        return -1;
    }

    sw_->set_signal_callback(std::bind(&signal_mgr::handle_signal, this, std::placeholders::_1));
    int ret = sw_->watch(SIGINT);
    if(ret != 0) return ret;
    
    ret = sw_->watch(SIGPIPE);
    if(ret != 0) return ret;

    ret = sw_->watch(SIGTERM);
    if(ret != 0) return ret;

    ret = sw_->watch(SIGUSR1);
    if(ret != 0) return ret;

    ret = sw_->watch(ON_MSG);
    if(ret != 0) return ret;

    return sw_->start();
}

void signal_mgr::handle_signal(const struct signalfd_siginfo* info) {
    static int count = 0;
    if (info == nullptr) return;

    //int signo = static_cast<int>(info->ssi_signo);
    //this->send_signal(info->ssi_int, signo);
    printf("recv count:%d\n", ++count);
}

int main(void) {
    uv_loop_t* loop = uv_default_loop();
    if (!loop) {
        sk_error("create default loop error.");
        return -1;
    }
    
    signal_mgr mgr(loop);
    mgr.watch_signals();

    uv_run(loop, UV_RUN_DEFAULT);

    return 0;
}
